package com.mydubbo.rpc.netty;

import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

import com.alibaba.fastjson.JSON;
import com.mydubbo.demo.UserService;
import com.mydubbo.rpc.Sender;
import com.mydubbo.rpc.Server;
import com.mydubbo.rpc.dto.Request;
import com.mydubbo.util.IpUtil;
import com.mydubbo.util.IpUtil.URL;
import com.mydubbo.util.Log;

public class NettyServer implements Server {

	@Override
	public void create(int port) {
		// 服务类,用于启动netty 在netty5中同样使用这个类来启动
		ServerBootstrap bootstrap = new ServerBootstrap();
		// 新建两个线程池  boss线程监听端口，worker线程负责数据读写
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();
		// 设置niosocket工厂  类似NIO程序新建ServerSocketChannel和SocketChannel
		bootstrap.setFactory(new NioServerSocketChannelFactory(boss, worker));
		// 设置管道的工厂
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				ChannelPipeline pipeline = Channels.pipeline();
				pipeline.addLast("decoder", new StringDecoder());
				pipeline.addLast("encoder", new StringEncoder());
				pipeline.addLast("serverHandler", new NettyServerHandler());  //添加一个Handler来处理客户端的事件，Handler需要继承ChannelHandler
				return pipeline;
			}
		});
		bootstrap.bind(new InetSocketAddress(port));
		System.out.println("start!!!");
	}

	@Override
	public Sender connect(String address) {
		// 客户端的启动类
		ClientBootstrap bootstrap = new ClientBootstrap();
		//线程池
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();
		//socket工厂
		bootstrap.setFactory(new NioClientSocketChannelFactory(boss, worker));
		//管道工厂
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				ChannelPipeline pipeline = Channels.pipeline();
				pipeline.addLast("decoder", new StringDecoder());
				pipeline.addLast("encoder", new StringEncoder());
				pipeline.addLast("clientHandler", new NettyClientHandler());
				return pipeline;
			}
		});
		//连接服务端
		URL url = IpUtil.toURL(address);
		Log.log("正在与" + url + "建立连接");
		ChannelFuture connect = bootstrap.connect(new InetSocketAddress(url.getIp(), url.getPort()));
		Channel channel = null;
		try {
			channel = connect.sync().getChannel();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
		
		return new NettySender(channel);
	}
	
	public static void main(String[] args) {
		Server server = new NettyServer();
		Sender sender = server.connect("127.0.0.1:20880");
		Request request = new Request();
		request.setId(UUID.randomUUID().toString());
		request.setClazz(UserService.class);
		request.setMethod("hello");
		request.setParameterTypes(new Class[]{String.class});
		request.setReturnType(Void.class);
		request.setArgs(new Object[]{"zhangsan"});
		sender.sendMessage(JSON.toJSONString(request));
	}

}
